package org.text2diagram.ddl.converter.dot;

import org.text2diagram.ddl.converter.DiagramDescription;
import org.text2diagram.ddl.domain.Block;
import org.text2diagram.ddl.domain.Color;
import org.text2diagram.ddl.domain.Group;
import org.text2diagram.ddl.domain.Link;

/**
 * Converter from base DDL diagram description into DOT format for further rendering
 * @author Svyatoslav Kryukov
 *
 * For DOT language syntax refer to: http://www.graphviz.org/pdf/dotguide.pdf
 */
public class DDLToDotConverter {
	
	public String convert(DiagramDescription ddl, String diagramName) {
		StringBuilder out = new StringBuilder();
		out.append("digraph " + diagramName + " {" + "\n");
		for (Block block : ddl.getBlockList()) {
			out.append(convertBlockToNode(block) + "\n"); 
		}
		for (Link link : ddl.getLinkList()) {
			if (link.getGroup() == null) { //go through top-level links only, links within clusters(groups) will be processed within the group
				out.append(convertLinkToEdge(link) + "\n");
			}
		}
		for (Group group: ddl.getGroupList()) {
			out.append(convertGroupToSubgraph(group) + "\n");
		}
		out.append("}");
		return out.toString();
	}
	
	private String convertBlockToNode(Block block) {
		StringBuilder out = new StringBuilder();
		out.append(String.format(
				"%s [shape=%s, style=filled, fillcolor=\"%s\"];", 
				block.getName(),
				Shape.convert(block.getAppearance()).name().toLowerCase(),
				convertColor(block.getColor())
			));		
		
		return out.toString();
	}
	
	/*
			LR_0 -> LR_1 [ label = "SS(S)" ];
			LR_1 -> LR_3 [ label = "S($end)" ];
	 */
	private String convertLinkToEdge(Link link) {
		StringBuilder out = new StringBuilder();
		out.append(
				String.format("%s -> %s [ label=\"%s\", dir=%s, style=%s];\n", 
								link.getSource().getName(),
								link.getTarget().getName(),
								link.getText(),
								EdgeDir.convert(link.getDirection()).name().toLowerCase(),
								EdgeStyle.convert(link.getStyle()).name().toLowerCase())
				);	
		
		return out.toString();
	}	
	
	/*
		subgraph cluster0 {
		node [style=filled,color=white];
		style=filled;
		color=lightgrey;
		a0 -> a1 -> a2 -> a3;
		label = "process #1";
		}
	 */
	private static int SUBGRAPH_SEQ = 0;
	private String convertGroupToSubgraph(Group group) {
		StringBuilder out = new StringBuilder();
		out.append("subgraph cluster" + SUBGRAPH_SEQ++ + " {\n") ;
		out.append("label = \"" + group.getName() + "\";\n");
		for (Link link : group.getLinks()) {
			out.append(convertLinkToEdge(link) + "\n");
		}
		out.append("}\n");
		return out.toString();
	}	
	
	private String convertColor(Color color) {
		return String.format("#%02X%02X%02X", 
				color.getRed(),
				color.getGreen(),
				color.getBlue());
	}
	
}
